package com.cloud.xtools.common.interceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.lang.reflect.Parameter;
import java.util.*;

/**
 * @author Daixinguo
 */
@Component
public class RequestInterceptor implements HandlerInterceptor {

    // 请求前执行
    // 返回 true 继续处理请求，返回 false 表示请求被拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // System.out.println("[preHandle] Request URL: " + request.getRequestURL());
        // System.out.println("[preHandle] Request Method: " + request.getMethod());

        if (handler instanceof HandlerMethod handlerMethod) {

            // 获取控制器类名
            // String controllerName = handlerMethod.getBeanType().getSimpleName();
            // System.out.println("Controller: " + controllerName);

            // 获取方法名
            // String methodName = handlerMethod.getMethod().getName();
            // System.out.println("Method: " + methodName);

            String uri = request.getRequestURI();

            // @PutMapping
            final var putMappingFuncAnnotation = handlerMethod.getMethod().getAnnotation(PutMapping.class);
            if (putMappingFuncAnnotation != null){
                // 获取方法的请求映射注解 @PutMapping 中设置的 uri 前缀
                // System.out.println(putMappingFuncAnnotation);
                if(Arrays.stream(putMappingFuncAnnotation.value()).findFirst().isEmpty()){
                    return true;
                }
                String uriTemplate = Arrays.stream(putMappingFuncAnnotation.value()).findFirst().get();
                if(!uriTemplate.startsWith("/")){
                    uriTemplate = "/" + uriTemplate;
                }

                // 获取控制器类的请求映射注解 @RequestMapping 中设置的 uri 前缀
                final var requestAnnotation = handlerMethod.getBeanType().getAnnotation(RequestMapping.class);
                String uriPrefix = null;
                if (requestAnnotation != null){
                    // System.out.println(requestAnnotation);
                    if(Arrays.stream(requestAnnotation.value()).findFirst().isPresent()){
                        // System.out.println(Arrays.stream(requestAnnotation.value()).findFirst().get());
                        uriPrefix = Arrays.stream(requestAnnotation.value()).findFirst().get();
                        if(!uriPrefix.startsWith("/")){
                            uriPrefix = "/" + uriPrefix;
                        }
                    }
                }

                // 去掉 uri 中的 @RequestMapping 注解指定的前缀
                if(uriPrefix != null){
                    uri = uri.replace(uriPrefix,"");
                }

                Map<String, Object> pathParameterValueMap = mapUriParameters(uriTemplate, uri);

                Parameter[] methodParameters = handlerMethod.getMethod().getParameters();
                List<String> paramNames = new ArrayList<>();
                for (Parameter parameter : methodParameters) {
                    paramNames.add(parameter.getName());
                }
                // System.out.println(paramNames);

                // 结合方法参数 methodParameters 从 pathParameterValueMap 取出有效的参数
                Map<String, Object> validPathParameterMap = new HashMap<>();
                for (String paramName : paramNames) {
                    if (pathParameterValueMap.containsKey(paramName)) {
                        validPathParameterMap.put(paramName, pathParameterValueMap.get(paramName));
                    }
                }
                // System.out.println(validPathParameterMap);
                // 将参数设置到 request 中
                request.setAttribute("pathParameters", validPathParameterMap);
            }


            // 获取方法的参数及其名称
            // 获取方法参数
            // MethodParameter[] parameters = handlerMethod.getMethodParameters();
            // Map<String, String[]> parameterMap = request.getParameterMap();
            // for (MethodParameter parameter : parameters) {
            //     System.out.println(parameter.getParameter());
            //     System.out.println(parameter.getParameterIndex());
            //     System.out.println(parameter.getParameterName());
            //     System.out.println(parameter.getMember());
            //     System.out.println(parameter.getNestingLevel());
            //     System.out.println(parameter.getTypeIndexForCurrentLevel());
            //
            //     System.out.println(request.getRequestURI());
            //
            //     System.out.println("========");
            //
            // }
        }

        return true;
    }

    // 请求后执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        // 处理完请求后，视图渲染之前执行
        // System.out.println("[postHandle] Response Status: " + response.getStatus());
    }

    // 完成请求处理后执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        // 清理工作，比如释放资源等
        // System.out.println("[afterCompletion] Request Completed!");
    }

    /**
     * 获取 URi 中的参数
     * @param template 请求模板   /users/{id}/orders/{order_id}
     * @param uri 请求 URI   /users/2/orders/3
     */
    public Map<String, Object> mapUriParameters(String template, String uri) {
        Map<String, Object> paramMap = new HashMap<>();

        // 将 template 和 uri 按 "/" 分割为数组
        String[] templateParts = template.split("/");
        String[] uriParts = uri.split("/");

        // 遍历 templateParts，找到带有 {} 的部分
        for (int i = 0; i < templateParts.length; i++) {
            String part = templateParts[i];
            if (part.startsWith("{") && part.endsWith("}")) {
                // 去掉 {} 获取参数名
                String paramName = part.substring(1, part.length() - 1);
                // 从 uriParts 获取对应的值
                paramMap.put(paramName, uriParts[i]);
            }
        }
        return paramMap;
    }
}
